package pl.makimo.fuzzy.sets;

import java.util.HashMap;

import pl.makimo.fuzzy.norms.Norm;
import pl.makimo.fuzzy.norms.Type2Norm;
import pl.makimo.fuzzy.sets.memberships.DiscreteMembershipFunction;

/* Chameleon class - works with all types of fuzzy sets, therefore it's not really clean */

public class Type2CompoundFuzzySet<T> extends FuzzySet<T> {
	public FuzzySet<T> set1;
	public FuzzySet<T> set2;
	
	public CrispSet<T> elements = new CrispSet<T>();
	
	public Norm norm;
		
	public Type2CompoundFuzzySet(FuzzySet<T> set1, FuzzySet<T> set2, Norm norm) {
		super();
		this.set1 = set1;
		this.set2 = set2;
		this.norm = norm;
		
		if (set1 instanceof Type2DiscreteFuzzySet) {
			this.elements = ((Type2DiscreteFuzzySet) set1).elements;
		} else if (set2 instanceof Type2DiscreteFuzzySet) {
			this.elements = ((Type2DiscreteFuzzySet) set2).elements;
		} else if (set1 instanceof Type2CompoundFuzzySet) {
			this.elements = ((Type2CompoundFuzzySet) set1).elements;
		} else if (set2 instanceof Type2CompoundFuzzySet) {
			this.elements = ((Type2CompoundFuzzySet) set2).elements;
		}
	}

	@Override
	public Object value(T element) {
		return norm.value(set1.value(element), set2.value(element));
	}	
	
    @Override
    public FuzzySet<T> support() {    	    	
    	HashMap<Object, Object> memberships = new HashMap<Object, Object>();
    	CrispSet<Double> newElements = new CrispSet<Double>();
    	
    	double size = 0.0;
    	
    	for (T element : elements) {     		
    		Object value = this.value(element);

    		if (value instanceof FuzzySet) {
    			size += ((FuzzySet)value).maxMembership();
   				memberships.put(element, ((FuzzySet)value).maxMembership());
    		}
    	}
    	
    	DiscreteFuzzySet set = new DiscreteFuzzySet(new DiscreteMembershipFunction(memberships));
    	set.elements = elements;
    	
    	return set;
    }
    
    @Override
    public double in() {
    	return (double)support().cardinality() / crispCardinality();
    }
    
    @Override
    public double crispCardinality() {
    	return (double)elements.cardinality();
    }
    
    @Override
    public double cardinality() {
    	return nfsigmaCount();
    }

    public double nfsigmaCount() {
    	double card = 0.0;
    	
    	for (T element : elements) {
    		FuzzySet set = (FuzzySet)this.value(element);
    		card += set.maxWithOne();
    	}
    	
    	return card;    	
    }

	@Override
	public double maxWithOne() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public double maxMembership() {
		// TODO Auto-generated method stub
		return 0;
	}
}
